/*
 * @Author: Liu jm (cdtye)
 * @Date: 2020-05-20 21:55:59
 * @LastEditTime: 2021-04-06 15:27:58
 * @LastEditors: Liu Zhiwang
 * @Description: 地图公用工具代码
 */
import axios from 'axios'
import qs from 'qs'
import { loadModules } from 'esri-loader'
import { getGisPath } from '@/api/gis/vector-editor'

// 私有方法
function getGeometrysExtent(geometrys, Extent) {
  let extent
  geometrys.forEach(geometry => {
    if (geometry.type === 'point') {
      if (!extent) {
        extent = new Extent(geometry.x, geometry.y, geometry.x, geometry.y, geometry.spatialReference)
      } else {
        extent = extent.union(new Extent(geometry.x, geometry.y, geometry.x, geometry.y, geometry.spatialReference))
      }
    } else {
      if (!extent) {
        extent = geometry.extent
      } else {
        extent = extent.union(geometry.extent)
      }
    }
  })
  return extent
}

/**
 *获取 GeometryArray或者 GraphicArray 的总范围
 *
 * @export
 * @param {*} elements GeometryArray或者 GraphicArray
 * @param {*} Extent esri/geometry/Extent
 * @returns elements中所有要素的范围总和
 */
export function getAllExtent(elements, Extent) {
  if (elements === undefined || elements === null) {
    return new Extent()
  } else {
    const geometrys = elements.map(element => {
      if (element.geometry) {
        return element.geometry
      } else {
        return element
      }
    })
    return getGeometrysExtent(geometrys, Extent)
  }
}

/**
 *获取线上的点
 *
 * @export
 * @param {*} line polyline
 * @param {*} ops center|start|end  配置 分别对应 中心点、起点，终点
 * @returns point
 */
export function getPointFromLine(line, ops) {
  if (line === undefined || line === null) {
    return null
  } else {
    let pathIndex = 0
    let pointIndex = 0
    if (ops === 'start') {
      pathIndex = 0
      pointIndex = 0
    } else if (ops === 'end') {
      pathIndex = line.paths.length - 1
      pointIndex = line.paths[pathIndex].length - 1
    } else {
      pathIndex = Math.floor(line.paths.length / 2)
      pointIndex = Math.floor(line.paths[pathIndex].length / 2)
    }
    return line.getPoint(pathIndex, pointIndex)
  }
}

/**
 * @description: 地图配置
 * @param {type}
 * @return:
 */
export const mapConfig = {
  // 自定义级别定义
  // 局 1-6
  // 段 7-9
  // 车间工区 10-18
  custLods: {
    // 总公司，预留属性，暂时不使用
    tlzgs: {
      defaultZoom: 4
    },
    // 铁路局
    tlj: {
      defaultZoom: 6
    },
    // 段
    segment: {
      defaultZoom: 8
    },
    // 车间、工区
    workshop: {
      defaultZoom: 12
    },
    // 级别字段对应名称 lingkl 2019年12月23日 新增
    deptLabel: {
      tlzgs: '总公司级',
      tlj: '路局级',
      segment: '段级',
      workshop: '车间/工区级'
    },
    // 可以使用zoom作为索引直接取到当前的级别
    reference: [
      // 'tlzgs',
      'tlj', 'tlj', 'tlj', 'tlj', 'tlj', 'tlj',
      'segment', 'segment', 'segment',
      'workshop', 'workshop', 'workshop', 'workshop', 'workshop', 'workshop', 'workshop', 'workshop', 'workshop'
    ]
  }
}

/**
 * @description:获取接触网平面布置图服务地址
 * liujm(cdtye) 2020年1月10日
 * @param {type} 区站编码
 * @return: 接触网平面布置图地图服务地址
 */
export async function getJcwPmbztServiceUrl(linesiteCode, type) {
  console.log(process.env)
  const baseUrl = process.env.VUE_APP_MAP_CAD_BASE.endsWith('/') ? process.env.VUE_APP_MAP_CAD_BASE : process.env.VUE_APP_MAP_CAD_BASE + '/'

  if (type !== undefined) {
    if (type === 2) { return baseUrl + linesiteCode + '/MapServer' } else {
      const res = await getGisPath({ gisQueryType: type, id: linesiteCode })
      return baseUrl + res.data + '/MapServer'
    }
  }

  if (process.env.VUE_APP_MAP_CAD_SERVERDIC && process.env.VUE_APP_MAP_CAD_SERVERDIC.length >= 1) {
    // 对于配置了接触网平面布置图服务字典的做匹配处理
    const servicesDic = process.env.VUE_APP_MAP_CAD_SERVERDIC.split(',')
    const serviceItem = servicesDic.find(x => x.split('|')[0] === linesiteCode)
    if (serviceItem) {
      const serviceName = serviceItem.split('|')[1]
      return baseUrl + serviceName + '/MapServer'
    } else {
      console.warn('线路区站' + linesiteCode + '接触网平面布置图服务未配置')
      return undefined
    }
  } else {
    // 没有配置时，直接用linessiteCode
    return baseUrl + linesiteCode + '/MapServer'
  }
}

/**
 * @description: 创建基础底图
 * @param {type}
 * IMG 卫星底图
 * IMGANNO 卫星地图包含标签
 * VEC 矢量电子地图
 * VECANNO 矢量电子地图包含标签
 * SIM 简易地图
 * @return:
 */
export function createBasemap(conf, Basemap, BaseTileLayer, WMTSLayer, MapImageLayer, code) {
  let basemapItems = conf.basemaps
  if (code && code.length >= 1) {
    basemapItems = basemapItems.filter(x => x.code === code)
  }
  return basemapItems.map((item) => {
    const lyrs = item.layers.map((lyrConf) => {
      if (lyrConf.layerType === 'WMTS') {
        return new WMTSLayer({
          url: lyrConf.url,
          serviceMode: conf.wmtsServiceMode
        })
      } else if (lyrConf.layerType === 'TDT_WMTS') {
        return createTdtWMTSLayer(lyrConf.url, BaseTileLayer)
      } else if (lyrConf.layerType === 'MapService') {
        return new MapImageLayer({
          url: lyrConf.url
        })
      }
    })
    return new Basemap({
      baseLayers: lyrs,
      id: item.code,
      title: item.title,
      thumbnailUrl: item.icon
    })
  })
}

/**
 * @description: 添加铁路主题相关图层
 * layersConfig '[{\"serviceName\":\"铁路线路\",\"labelName\":\"铁路线\",\"serviceType\":\"MapService\",\"serviceUrl\":\"http://172.20.1.9:13772/arcgis/rest/services/GZJ_BZGTL_W/MapServer\",\"serviceCode\":\"BZGTL\",\"isShowLyrM\":0,\"isVisible\":1,\"isUsed\":1,\"orderNum\":0},{\"serviceName\":\"公里标\",\"labelName\":\"公里标\",\"serviceType\":\"MapService\",\"serviceUrl\":\"http://172.20.1.9:13772/arcgis/rest/services/GLB_W/MapServer\",\"serviceCode\":\"GLB\",\"isShowLyrM\":1,\"isVisible\":1,\"isUsed\":1,\"orderNum\":1},{\"serviceName\":\"火车站\",\"labelName\":\"车站\",\"serviceType\":\"MapService\",\"serviceUrl\":\"http://172.20.1.9:13772/arcgis/rest/services/GZJ_CZ_W/MapServer\",\"serviceCode\":\"CZ\",\"isShowLyrM\":1,\"isVisible\":1,\"isUsed\":1,\"orderNum\":2},{\"serviceName\":\"车站注记\",\"labelName\":\"车站注记\",\"serviceType\":\"MapService\",\"serviceUrl\":\"http://172.20.1.9:13772/arcgis/rest/services/GZJ_CZZJ_W/MapServer\",\"serviceCode\":\"CZZJ\",\"isShowLyrM\":1,\"isVisible\":1,\"isUsed\":1,\"orderNum\":3}]'
 * 请使用接口 basic/gisMapService/ 获取数据
 * @param {type}
 * @return:
 */
export function addRaiwayLayers(map, BaseTileLayer, WMTSLayer, MapImageLayer, layersConfig) {
  layersConfig.reverse().forEach((item) => {
    if (item.serviceType === 'WMTS') {
      const lyr = new WMTSLayer({
        title: item.labelName ? item.labelName : item.serviceName,
        url: item.serviceUrl,
        visible: (item.isVisible === 1),
        id: item.code,
        listMode: item.isVisible === 0 ? 'hide' : 'hide-children',
        serviceMode: 'kvp'
      })
      map.layers.add(lyr, 0)
    } else if (item.serviceType === 'TDT_WMTS') {
      const lyr = createTdtWMTSLayer(item.serviceUrl, BaseTileLayer)
      // eslint-disable-next-line no-sequences
      lyr.title = item.labelName ? item.labelName : item.serviceName,
      lyr.visible = (item.isVisible === 1)
      lyr.id = item.code
      lyr.listMode = item.isVisible === 0 ? 'hide' : 'hide-children'
      map.layers.add(lyr, 0)
    } else if (item.serviceType === 'MapService') {
      const lyr = new MapImageLayer({
        title: item.labelName ? item.labelName : item.serviceName,
        url: item.serviceUrl,
        visible: (item.isVisible === 1),
        id: item.code,
        listMode: item.isVisible === 0 ? 'hide' : 'hide-children'
      })
      map.layers.add(lyr, 0)
    }
  })
}
// 创建天地图wmtslayer
export function createTdtWMTSLayer(url, BaseTileLayer) {
  // ASE_CIA_W 全国影像注记
  // BASE_IMG_W 全国影像
  const layerProperties = {
    version: '1.0.0',
    identifier: 'img',
    style: 'default',
    tileMatrixSetId: 'w'
  }
  if (url.indexOf('BASE_IMG_W') >= 0) {
    layerProperties.identifier = 'img'
    layerProperties.tileMatrixSetId = 'w'
  } else if (url.indexOf('BASE_CIA_W')) {
    layerProperties.identifier = 'cia'
    layerProperties.tileMatrixSetId = 'w'
  }
  const TdtLayer = BaseTileLayer.createSubclass({
    properties: layerProperties,
    getTileUrl: function(l, r, c) { // ?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=cia&STYLE=default&FORMAT=tiles&TILEMATRIXSET=w&TILEMATRIX=4&TILEROW=7&TILECOL=13&token=undefined
      return this.url +
     '?SERVICE=WMTS&VERSION=' + this.version +
     '&REQUEST=GetTile&LAYER=' + this.identifier +
     '&STYLE=' + this.style +
     '&FORMAT=tiles&TILEMATRIXSET=' + this.tileMatrixSetId +
     '&TILEMATRIX=' + l + '&TILEROW=' + r + '&TILECOL=' + c
    }
  })
  return new TdtLayer({ url: url, spatialReference: { wkid: 102100 }})
}

/**
 * @description: 执行ArcGIS Server的登录注册
 * @param {type}
 * @return:
 */
export function loginArcGISServer() {
  loadModules([
    'esri/identity/IdentityManager'
  // eslint-disable-next-line no-undef
  ], { url: tyeMapConf().jsapi })
    .then(([
      esriId
    ]) => {
      if (process.env.VUE_APP_ARCGIS_AUTH && process.env.VUE_APP_ARCGIS_AUTH.length >= 1) {
        const arcgis_auth = process.env.VUE_APP_ARCGIS_AUTH
        const username = arcgis_auth.split(',')[0]
        const password = arcgis_auth.split(',')[1]
        axios.post(process.env.VUE_APP_ARCGIS_BASE + 'tokens/', qs.stringify({
          request: 'getToken',
          username: username,
          password: password
        }))
          .then(response => {
            if (response.data.length > 0) {
              esriId.registerToken({ server: process.env.VUE_APP_ARCGIS_BASE + 'rest/services', token: response.data })
              console.log('ArcGIS服务登录成功')
            } else {
              console.error('ArcGIS服务登录失败,请检查配置项 VUE_APP_ARCGIS_AUTH 的' + arcgis_auth + '值是否正确')
            }
          })
          .catch(function(error) {
            console.error('ArcGIS服务登录失败,请检查配置项 VUE_APP_ARCGIS_AUTH 的' + arcgis_auth + '值是否正确')
            console.error(error)
          })
      }
    })
}

/**
 *将 esri/geometry 转换成 本系统约定的 Geojson 数字均保留8位小数
 *
 * @export
 * @param {*} geometry esri/geometry 的子类（Point|Polyline|Polygon）
 * @returns Geojson对象
 */
export function geometryToGeojson(geometry) {
  if (!geometry) return null
  let geojson
  if (geometry.type === 'point' || (geometry.x && geometry.y)) {
    geojson = {
      'type': 'Point',
      'coordinates': [Number(geometry.x.toFixed(8)), Number(geometry.y.toFixed(8))]
    }
  } else if (geometry.type === 'polyline' || geometry.paths) {
    const paths = geometry.paths.length <= 1 ? geometry.paths[0] : geometry.paths
    fixedArrayNum(paths, 8)
    geojson = {
      'type': geometry.paths.length <= 1 ? 'LineString' : 'MultiLineString',
      'coordinates': paths
    }
  } else if (geometry.type === 'polygon' || geometry.rings) {
    const rings = geometry.rings
    fixedArrayNum(rings, 8)
    geojson = {
      'type': 'Polygon',
      'coordinates': rings
    }
  } else {
    console.warn('不支持的几何类型', geometry)
  }
  return geojson
}

/**
 *将 esri/geometry 转换成 本系统约定的 Json 数字均保留两位小数
 *包含两个属性 type 和 （xy|paths|rings）
 * @export
 * @param {*} geometry esri/geometry 的子类（Point|Polyline|Polygon）
 * @returns geometry json 对象
 */
export function geometryToJson(geometry) {
  if (!geometry) return null

  let geostr
  if (geometry.type === 'point') {
    const x = geometry.x
    const y = geometry.y
    geostr = {
      'x': Number(x.toFixed(2)),
      'y': Number(y.toFixed(2))
    }
  } else if (geometry.type === 'polyline') {
    const paths = geometry.paths
    fixedArrayNum(paths, 2)
    geostr = {
      'paths': paths
    }
  } else if (geometry.type === 'polygon') {
    const rings = geometry.rings
    fixedArrayNum(rings, 2)
    geostr = {
      'rings': rings
    }
  }
  return geostr
}

/**
 *对给定的数组中的数字做小数位数处理
 *
 * @export
 * @param {*} source 数组
 * @param {*} num  要保留的小数位数
 */
export function fixedArrayNum(source, num) {
  for (var i = 0; i < source.length; i++) {
    if (source[i] instanceof Array) {
      fixedArrayNum(source[i], num)
    } else {
      source[i] = parseFloat(source[i].toFixed(num))
    }
  }
}

/**
 *生成随机颜色
 *
 * @export
 * @returns 16进制表示的颜色
 */
export function getRandomColor() {
  return '#' + Math.floor(Math.random() * 16777215).toString(16)
}

/**
 *墨卡托坐标转换为wgs84坐标
 *
 * @export
 * @returns 16进制表示的颜色
 */
export function mercator2wgs84(coords) {
  let { x, y } = coords
  let isArray = false
  if (!x) {
    isArray = true
    x = coords[0]
    y = coords[1]
  }
  x = x / 20037508.34 * 180
  y = y / 20037508.34 * 180
  y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2)
  x = Number(Number(x).toFixed(8))
  y = Number(Number(y).toFixed(8))
  return isArray ? [x, y] : { x, y }
}
